home *** CD-ROM | disk | FTP | other *** search
/ System Booster / System Booster.iso / Archives / ARexxTools / fpl70.lha / src / memory.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-04-10  |  16.3 KB  |  610 lines

  1. /******************************************************************************
  2.  *                   FREXX PROGRAMMING LANGUAGE                  *
  3.  ******************************************************************************
  4.  
  5.  memory.c
  6.  
  7.  Memory functions handling all allocating and freeing.
  8.  
  9.  *****************************************************************************/
  10.  
  11. /************************************************************************
  12.  *                                                                      *
  13.  * fpl.library - A shared library interpreting script langauge.         *
  14.  * Copyright (C) 1992-1994 FrexxWare                                    *
  15.  * Author: Daniel Stenberg                                              *
  16.  *                                                                      *
  17.  * This program is free software; you may redistribute for non          *
  18.  * commercial purposes only. Commercial programs must have a written    *
  19.  * permission from the author to use FPL. FPL is *NOT* public domain!   *
  20.  * Any provided source code is only for reference and for assurance     *
  21.  * that users should be able to compile FPL on any operating system     *
  22.  * he/she wants to use it in!                                           *
  23.  *                                                                      *
  24.  * You may not change, resource, patch files or in any way reverse      *
  25.  * engineer anything in the FPL package.                                *
  26.  *                                                                      *
  27.  * This program is distributed in the hope that it will be useful,      *
  28.  * but WITHOUT ANY WARRANTY; without even the implied warranty of       *
  29.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.                 *
  30.  *                                                                      *
  31.  * Daniel Stenberg                                                      *
  32.  * Ankdammsgatan 36, 4tr                                                *
  33.  * S-171 43 Solna                                                       *
  34.  * Sweden                                                               *
  35.  *                                                                      *
  36.  * FidoNet 2:201/328    email:dast@sth.frontec.se                       *
  37.  *                                                                      *
  38.  ************************************************************************/
  39.  
  40. #ifdef UNIX
  41. #include <sys/types.h>
  42. #elif defined(AMIGA)
  43. #include <exec/types.h>
  44. #include <exec/memory.h>
  45. #include <proto/exec.h>
  46. #endif
  47.  
  48. #include <stdio.h>
  49. #include <stdlib.h>
  50. #include <stddef.h>
  51. #include "script.h"
  52. #include "memory.h"
  53.  
  54. static void  LinkMemory(struct Data *, struct MemInfo *, char);
  55. static void  UnLinkMemory(struct Data *, struct MemInfo *, char);
  56.  
  57. #ifdef DEBUG
  58. extern long mem;
  59. extern long maxmem;
  60. long malloc_count=0;
  61. long Mmalloc_count=0;
  62. long free_mem=0;
  63. long max_free_mem=0;
  64. #endif
  65.  
  66. /**********************************************************************
  67.  *
  68.  * MallocCycle();
  69.  *
  70.  * Get memory to a MALLOC_DYNAMIC alloc. The memory can be taken from the
  71.  * memory cache if any is available.
  72.  *
  73.  ******/
  74.  
  75. void  *MallocCycle(struct Data *scr, long size DEBUGPARAMETERS2)
  76. {
  77.   if(size<256) {
  78.     register struct FreeBlock *pnt;
  79.     size>>=4;
  80.     if(pnt=scr->blox[size]) {
  81.       scr->blox[size]=pnt->next;
  82.       scr->blockcount[size]--;
  83. #ifdef DEBUG
  84. #ifdef DEBUGPARAMETERS2
  85.       pnt->mem.line=line;
  86.       pnt->mem.source=source; /* the two debugparameters */
  87. #endif
  88.       Mmalloc_count++;
  89.       free_mem-=(((struct MemInfo *)pnt)->size&SIZEBITS)+
  90.     sizeof(struct MemInfo);
  91.       CheckMem(scr, (char *)pnt+sizeof(struct MemInfo));
  92. #endif
  93.       return (void *)((char *)pnt+sizeof(struct MemInfo));
  94.     } else
  95.       size=(size<<4)+15;
  96.   }
  97.  
  98. #ifdef DEBUG
  99. #ifdef DEBUGPARAMETERS2
  100.   return Malloc(scr, size, MALLOC_DYNAMIC, source, line);
  101. #endif
  102. #else
  103.   return Malloc(scr, size, MALLOC_DYNAMIC);
  104. #endif
  105. }
  106.  
  107. /**********************************************************************
  108.  *
  109.  * DefaultAlloc();
  110.  *
  111.  * THis function allocates memory from the system. Replaceable with the
  112.  * tag FPLTAG_INTERNAL_ALLOC.
  113.  *
  114.  ******/
  115.  
  116. void ASM *DefaultAlloc(DREG(0) long size)
  117. {
  118. #ifdef AMIGA
  119.   return (void *)AllocMem(size, MEMF_ANY);
  120. #elif defined(UNIX)
  121.   return (void *)malloc(size);
  122. #endif
  123. }
  124.  
  125. /**********************************************************************
  126.  *
  127.  * DefaultDealloc();
  128.  *
  129.  * This functions does nothing but returns allocated memory to the system.
  130.  * It can be replaced by a user function specified with the tag
  131.  * FPLTAG_INTERNAL_DEALLOC.
  132.  *
  133.  ******/
  134.  
  135. void ASM DefaultDealloc(AREG(1) void *point, DREG(0) long size)
  136. {
  137. #ifdef AMIGA  
  138.   FreeMem(point, size);
  139. #elif UNIX
  140.   free(point);
  141. #endif
  142. }
  143.  
  144. /**********************************************************************
  145.  *
  146.  * Malloc();
  147.  *
  148.  * Allocate memory for real.
  149.  *
  150.  ******/
  151.  
  152. void ASM *Malloc(AREG(0) struct Data *scr, DREG(0) long size, DREG(1) char type
  153.          DEBUGPARAMETERS1)
  154. {
  155.   char *alloc;
  156.  
  157. #ifdef DEBUG
  158.   struct MemInfo *meminfo;
  159.  
  160.   size+=MEMORY_COOKIE; /* add extra bytes after the block! */
  161. #endif
  162.  
  163.   alloc=(char *)scr->Alloc(size+sizeof(struct MemInfo));
  164.  
  165.   if(!alloc) {
  166.     /* If the first alloc failed, flush caches and retry! */
  167.     FlushFree(scr);
  168.     alloc=(char *)scr->Alloc(size+sizeof(struct MemInfo));
  169.     if(!alloc)
  170.       return(NULL);
  171.   }
  172.  
  173.   ((struct MemInfo *)alloc)->size=size | (type * ALLOCBIT);
  174.   /* size = size | (type * 1<<31) */
  175.  
  176.   LinkMemory(scr, (struct MemInfo *)alloc, type);
  177.  
  178. #ifdef DEBUG
  179.   meminfo=(struct MemInfo *)alloc;
  180.  
  181. #if PRE_COOKIE>0
  182.   /* Fill the pre_cookie with junk too! */
  183.   memset((void *)meminfo->dummy, 0xbb,
  184.      sizeof(struct MemInfo)-offsetof(struct MemInfo, dummy));
  185. #endif
  186.  
  187. #if MEMORY_COOKIE>0
  188.   memset((char *)meminfo + sizeof(struct MemInfo) + size-MEMORY_COOKIE,
  189.      0xbb, MEMORY_COOKIE);
  190. #endif
  191.  
  192. #ifdef DEBUGPARAMETERS2
  193.   meminfo->line=line;
  194.   meminfo->source=source; /* the two debugparameters */
  195. #endif
  196.  
  197.   Mmalloc_count++;
  198.   malloc_count++;
  199.   mem+=size+sizeof(struct MemInfo);
  200.   if(mem>maxmem)
  201.     maxmem=mem;
  202. #endif
  203.   return (void *) ((char *)alloc+sizeof(struct MemInfo));
  204. }
  205.  
  206. /**********************************************************************
  207.  *
  208.  * LinkMemory();
  209.  *
  210.  * Adds the specifed memory area to the certain memory type list.
  211.  *
  212.  *****/
  213.  
  214. static void 
  215. LinkMemory(struct Data *scr,
  216.            struct MemInfo *point,
  217.            char type)
  218. {
  219.   point->prev=scr->MallocKey[type];     /* previous */
  220.   point->next=NULL;         /* next */
  221.   if(scr->MallocKey[type])
  222.     point->prev->next=point;
  223.   scr->MallocKey[type] = (void *)point;
  224. }
  225.  
  226.  
  227. /**********************************************************************
  228.  *
  229.  * UnLinkMemory();
  230.  *
  231.  * Deletes the specifed memory area from the certain memory type list.
  232.  *
  233.  *****/
  234.  
  235. static void 
  236. UnLinkMemory(struct Data *scr,
  237.              struct MemInfo *point,
  238.              char type)
  239. {
  240.   if(scr->MallocKey[type]==point) {
  241.     /* if this is the last Malloc, set `last' to `prev' */
  242.     scr->MallocKey[type]=point->prev;
  243.     if(scr->MallocKey[type])
  244.       scr->MallocKey[type]->next=NULL;
  245.   } else {
  246.     /* point the previous' `next' to our `next', and our next `previous'
  247.        to our `previous'. Unlink us from the chain */
  248.     if(point->prev)
  249.       /* only if we aren't the _first_ Malloc() ! */
  250.       point->prev->next=point->next;
  251.     if(point->next)
  252.       /* only if there is a next! */
  253.       point->next->prev=point->prev;
  254.   }
  255. }
  256.  
  257.  
  258. /**********************************************************************
  259.  *
  260.  * FreeCycle();
  261.  *
  262.  * Free the MALLOC_DYNAMIC allocated memory to the memory cache, or if
  263.  * that is full, free for real.
  264.  *
  265.  * In this routine we do not have to bitwise and SIZEBITS since the ALLOCBIT
  266.  * is never set when this is called!
  267.  *
  268.  ******/
  269.  
  270. void  FreeCycle(struct Data *scr, void *ptr)
  271. {
  272.   struct MemInfo *point=(struct MemInfo *)((char *)ptr-sizeof(struct MemInfo));
  273.   /* `point' points to the MemInfo structure */
  274. #if defined(DEBUG) && defined(UNIX)
  275.   if(point->size&ALLOCBIT) {
  276.     fprintf(stderr, "*WARNING* Illegal free() of %d bytes!\n",
  277.         point->size&SIZEBITS);
  278.   }
  279. #endif
  280.  
  281. #ifdef DEBUG
  282.   CheckMem(scr, ptr);
  283. #endif
  284.  
  285. #if MEMORY_QUEUE>0
  286.   if(point->size<256+MEMORY_COOKIE) {
  287.     register long size=point->size-MEMORY_COOKIE>>4;
  288.     if(scr->blockcount[size]<MEMORY_QUEUE_SIZE) {
  289. #ifdef DEBUG
  290.       memset(ptr, 0xaa, point->size-MEMORY_COOKIE);
  291.  
  292.       free_mem+=point->size+sizeof(struct MemInfo);
  293.       if(free_mem>max_free_mem)
  294.     max_free_mem=free_mem;
  295. #endif
  296.       ((struct FreeBlock *)point)->next=scr->blox[size];
  297.       scr->blox[size]=(struct FreeBlock *)point;
  298.       scr->blockcount[size]++;
  299.       return;
  300.     }
  301.   }
  302. #endif
  303.   Free(scr, ptr, MALLOC_DYNAMIC);
  304. }
  305.  
  306. /**********************************************************************
  307.  *
  308.  * Free();
  309.  *
  310.  * Free a allocated memory area of a certain type. The freed memory
  311.  * area gets freed `for real'.
  312.  *
  313.  *****/
  314.  
  315. void ASM Free(AREG(0) struct Data *scr, AREG(1) void *ptr, DREG(0) char type)
  316. {
  317.   struct MemInfo *point=(struct MemInfo *)((char *)ptr-sizeof(struct MemInfo));
  318.   /* `point' points to the MemInfo structure: */
  319. #ifdef DEBUG
  320.   CheckMem(scr, ptr);
  321. #endif
  322.   UnLinkMemory(scr, point, type);
  323. #ifdef DEBUG
  324.   mem-=(point->size&SIZEBITS)+sizeof(struct MemInfo);
  325. #endif
  326.   scr->Dealloc(point, (point->size&SIZEBITS)+sizeof(struct MemInfo));
  327. }
  328.  
  329. #ifdef DEBUG
  330. /**********************************************************************
  331.  *
  332.  * CheckMem();
  333.  *
  334.  * Check a special malloc to see that it hasn't overwritten it's boundaries.
  335.  *
  336.  ******/
  337.  
  338. ReturnCode  CheckMem(struct Data *scr, void *ptr)
  339. {
  340.   long i;
  341.   long b, c;
  342.   unsigned char *data;
  343.   struct MemInfo *point;
  344.   /* `point' points to the MemInfo structure: */
  345.   point=(struct MemInfo *)((char *)ptr-sizeof(struct MemInfo));
  346.  
  347. #if MEMORY_COOKIE>0
  348.   for(i=b=0;i<MEMORY_COOKIE; i++) {
  349.     data=(char *)point+ sizeof(struct MemInfo)+i+(point->size&SIZEBITS)-MEMORY_COOKIE;
  350.     if(*data!= 0xbb)
  351.       b++;
  352.   }
  353.  
  354.   if(b) {
  355. #ifdef AMIGA
  356.     /* ERROR */
  357.     point=NULL;
  358. #else
  359.     fprintf(stderr, "Memory violation: malloc(%d) was abused %d bytes after block!\n",
  360.         (point->size&SIZEBITS), b);
  361. #endif
  362.   }
  363. #endif
  364.  
  365. #if PRE_COOKIE>0
  366.   for(c=i=0;i<sizeof(struct MemInfo)-offsetof(struct MemInfo, dummy); i++)
  367.     if(point->dummy[i]!= 0xbb)
  368.       c++;
  369.  
  370.   if(c) {
  371. #ifdef AMIGA
  372.     /* ERROR */
  373.     point=NULL;
  374. #else
  375.     fprintf(stderr, "Memory violation: malloc(%d) was abused %d bytes before block!\n",
  376.         (point->size&SIZEBITS), c);
  377. #endif
  378.   }
  379. #endif
  380.  
  381.   return(b+c?FPL_OUT_OF_MEMORY:FPL_OK);
  382. }
  383. #endif
  384.  
  385. /**********************************************************************
  386.  *
  387.  * FreeAll();
  388.  *
  389.  * Free all memory allocated with specified type!
  390.  *
  391.  ******/
  392.  
  393. void  FreeAll(struct Data *scr, char type)
  394. {
  395.   struct MemInfo *point;
  396.   void *prev;
  397. #ifdef DEBUG
  398.   long size;
  399. #endif
  400.   if(!scr->MallocKey[type])
  401.     return;
  402.   do {
  403.     point=scr->MallocKey[type];
  404.     /* `point' points to the MemInfo structure! */
  405.  
  406.     prev=(void *)point->prev;
  407.  
  408. #ifdef DEBUG
  409.     mem-=(point->size&SIZEBITS)+sizeof(struct MemInfo);
  410.     size=(point->size&SIZEBITS);
  411.  
  412.     if(type == MALLOC_DYNAMIC)
  413.       free_mem=0; /* no free mem left in memory queuing */
  414. #endif
  415.     scr->Dealloc(scr->MallocKey[type], (point->size&SIZEBITS)+sizeof(struct MemInfo));
  416.   } while(scr->MallocKey[type]=prev);
  417.   if(type==MALLOC_DYNAMIC)
  418.     InitFree(scr); /* init the memory cache tables to prevent accidents with
  419.               FPLSEND_FLUSHCACHE */
  420. }
  421.  
  422. #if 0
  423. if(type) {
  424.   /* MALLOC_STATIC */
  425.   FREEA((char *)point+sizeof(struct MemInfo));
  426. } else {
  427.   /* MALLOC DYNAMIC */
  428.   FREE((char *)point+sizeof(struct MemInfo));
  429. }
  430. #endif
  431.  
  432. /**********************************************************************
  433.  *
  434.  * InitFree()
  435.  *
  436.  * Initialize the memory cache/queue.
  437.  *
  438.  ******/
  439.  
  440. void InitFree(struct Data *scr)
  441. {
  442.   memset(scr->blox, 0, sizeof(struct FreeBlock *)*BLOCK_ENTRIES);
  443.   memset(scr->blockcount, 0, sizeof(long)*BLOCK_ENTRIES);
  444. }
  445.  
  446. /**********************************************************************
  447.  *
  448.  * FlushFree();
  449.  *
  450.  * Flush the memory chache.
  451.  *
  452.  *******/
  453.  
  454. void FlushFree(struct Data *scr)
  455. {
  456.   register long i;
  457.   for(i=0; i<BLOCK_ENTRIES;i++) {
  458.     register struct FreeBlock *pnt;
  459.     while(pnt=scr->blox[i]) {
  460.       scr->blox[i]=pnt->next; /* delete block from chain */
  461.       scr->blockcount[i]--;   /* count down counter */
  462.       /* free block for real */
  463.       Free(scr, (char *)pnt+sizeof(struct MemInfo), MALLOC_DYNAMIC);
  464.     }
  465.   }
  466. }
  467.  
  468. /**********************************************************************
  469.  *
  470.  * SwapMem();
  471.  *
  472.  * If type is MALLOC_STATIC or MALLOC_DYNAMIC, this function will secure that
  473.  * the memory area will be of that kind!
  474.  *
  475.  * THE AREA MUST BE ALLOCATED WHEN THIS CONVERTION HAPPENS!!! IT MUST NOT
  476.  * BE IN THE FREE MEMORY CACHE/QUEUE LIST.
  477.  *
  478.  * This function is mainly used when storing global data. Since all
  479.  * MALLOC_DYNAMIC data gets freed at the end of a FPL program run, we must
  480.  * convert the mallocs to be able to keep them for next execution!
  481.  *
  482.  *****/
  483.  
  484. void SwapMem(struct Data *scr, void *ptr, char type)
  485. {
  486.   struct MemInfo *point=(struct MemInfo *)((char *)ptr-sizeof(struct MemInfo));
  487.   /* `point' points to the MemInfo structure: */
  488.   if(point->size&ALLOCBIT && type==MALLOC_DYNAMIC) {
  489.     /* This is a MALLOC_STATIC alloc */
  490.     UnLinkMemory(scr, point, MALLOC_STATIC); /* take away from static list */
  491.     point->size&=SIZEBITS;
  492.     LinkMemory(scr, point, MALLOC_DYNAMIC);  /* insert in dynamic list */
  493.   } else if(!(point->size&ALLOCBIT) && type==MALLOC_STATIC) {
  494.     /* This is a MALLOC_DYNAMIC alloc */
  495.     UnLinkMemory(scr, point, MALLOC_DYNAMIC); /* take away from dynamic list */
  496.     point->size|=ALLOCBIT;
  497.     LinkMemory(scr, point, MALLOC_STATIC);    /* insert in static list */
  498.   }
  499.   /* If no if() statement was reached, the memory area type was corect! */
  500. }
  501.  
  502. /**********************************************************************
  503.  *
  504.  * fplAlloc()
  505.  *
  506.  * fplAlloc() allocates memory and assign it to the fpl internal list of
  507.  * used memory. If fplFree() is called, this memory area will be free'd if
  508.  * not earlier. Free this memory using fplDealloc().
  509.  *
  510.  ******/
  511.  
  512. void PREFIX *fplAlloc(AREG(0) struct Data *scr, DREG(0) long size)
  513. {
  514.   if(!scr)
  515.     return(NULL);
  516.   return MALLOCA(size);
  517. }
  518.  
  519. /**********************************************************************
  520.  *
  521.  * fplDealloc()
  522.  *
  523.  * This function frees memory previously allocated with fplAlloc();
  524.  *
  525.  *****/
  526.  
  527. void PREFIX fplDealloc(AREG(0) struct Data *scr, AREG(1) void *ptr)
  528. {
  529.   if(!scr)
  530.     return;
  531.   FREEA(ptr);
  532. }
  533.  
  534. /**********************************************************************
  535.  *
  536.  * fplAlloca()
  537.  *
  538.  * fplAlloca() allocates memory and assign it to the fpl internal list of
  539.  * used memory. The memory will only exist while executing the current file or
  540.  * until next program has been executed. If fplFree() is called, this memory
  541.  * area will also be free'd. Free this memory using fplDealloca(). This function
  542.  * will use the FPL internal memory caching system.
  543.  *
  544.  ******/
  545.  
  546. void PREFIX *fplAlloca(AREG(0) struct Data *scr, DREG(0) long size)
  547. {
  548.   if(!scr)
  549.     return(NULL);
  550.   return MALLOC(size);
  551. }
  552.  
  553. /**********************************************************************
  554.  *
  555.  * fplDealloca()
  556.  *
  557.  * This function frees memory previously allocated with fplAlloca();
  558.  *
  559.  *****/
  560.  
  561. void PREFIX fplDealloca(AREG(0) struct Data *scr, AREG(1) void *ptr)
  562. {
  563.   if(!scr)
  564.     return;
  565.   FREE(ptr);
  566. }
  567.  
  568. /***************************************************************
  569.  *
  570.  * fplAllocString()
  571.  *
  572.  * Returns a pointer to a memory block of the requested size.
  573.  * The memory block is initialized as a string and can be used
  574.  * when returning strings to FPL with fplSend(), without having
  575.  * to allocate memory, make FPL have to allocate memory and copy
  576.  * all your data and then you free your memory again.
  577.  *  Now all you have to do is allocate a string at once and then
  578.  * tell FPL in fplSend() using the FPLSEND_DONTCOPY_STRING. The memory
  579.  * block will then be used as it is by FPL.
  580.  *
  581.  * If you want to free the memory, you do that with fplFreeString().
  582.  * You must not free memory sent to FPL!
  583.  *
  584.  ********/
  585.  
  586. void PREFIX *fplAllocString(AREG(0) struct Data *scr, DREG(0) long size)
  587. {
  588.   struct fplStr *ptr = MALLOCA(size + sizeof(struct fplStr)); 
  589.  
  590.   if(!ptr)
  591.     return NULL;
  592.  
  593.   ptr->alloc=size;
  594.  
  595.   ptr+=offsetof(struct fplStr, string); /* make 'ptr' point to the string
  596.                        entry */
  597.   return ptr; /* return string must be freed with fplFreeString() */
  598. }
  599.  
  600. void PREFIX fplFreeString(AREG(0) struct Data *scr, AREG(1) void *ptr)
  601. {
  602.   char *point=ptr;
  603.   if(!point)
  604.     return;
  605.  
  606.   point-=offsetof(struct fplStr, string); /* go to beginning of allocation */
  607.  
  608.   FREEA(point); /* free the string! */
  609. }
  610.